package com.hb.trade.api.im.chat.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hb.core.pojo.im.entity.ChatRecord;
import com.hb.core.pojo.im.mapper.ChatRecordMapper;
import com.hb.trade.api.im.chat.service.ChatRecordService;
import com.hb.trade.api.im.chat.service.ChatUserService;
import com.hb.trade.api.im.chat.service.ChatRecordContentService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.fzzn.core.model.user.layim.LayImUser;
import org.fzzn.core.model.websocket.SocketMessageEntity;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * <p>
 * 聊天记录表 服务实现类
 * </p>
 *
 * @author zhaojk
 * @since 2021-12-30
 */
@Service
public class ChatRecordServiceImpl extends ServiceImpl<ChatRecordMapper, ChatRecord> implements ChatRecordService {

    protected final ChatUserService chatUserService;
    protected final ChatRecordContentService chatRecordContentService;

    public ChatRecordServiceImpl(ChatUserService chatUserService,
                                 ChatRecordContentService chatRecordContentService) {
        this.chatUserService = chatUserService;
        this.chatRecordContentService = chatRecordContentService;
    }

    /**
     * 记录消息
     * 该方法记录的聊天消息只为支持离线消息使用
     * 聊天记录的查询需要查询im_chat_record_content表
     * 该方法被调用时会操作im_chat_record_content表进行保存
     * 该方法未调用事务
     *
     * @param message      消息正文(layim接收的完整格式)
     * @param toUname      接收人
     * @param isOfflineMsg 是否离线消息
     */
    @Override
    public void record(SocketMessageEntity message, String toUname, boolean isOfflineMsg) {
        boolean isRecord = message.isRecord();
        if (!isRecord) {
            return;
        }
        ChatRecord record = new ChatRecord();
        JSONObject contentData = message.getContentData();
        if (contentData == null) {
            log.warn("IM聊天内容消息体为空, 忽略记录");
            return;
        }

        // ************************************ 解析发送人信息 ************************************
        // 消息来源ID
        Long id = contentData.getLong("id");
        record.setFromAreaId(id);
        // 消息发送人ID
        Long fromId = contentData.getLong("fromid");
        record.setFromId(fromId);
        // 发送人websocket标识
        String fromName = message.getFromName();
        if (StrUtil.isNotEmpty(fromName)) {
            record.setFromName(fromName);
        }

        // ************************************ 接收人信息 ************************************
        LayImUser imUser = chatUserService.getLayimMine(toUname);
        if (imUser == null) {
            return;
        }
        record.setToId(NumberUtil.parseLong(imUser.getId()));
        record.setToName(toUname);
        // 聊天内容
        record.setContent(message.toString());
        record.setMsgType(isOfflineMsg ? 2 : 1);
        record.setMsgId(message.getId());
        record.buildBaseData(1);
        save(record);
        // 添加到聊天记录
        chatRecordContentService.saveFromRecord(record);
    }
    /**
     * 查询指定接收人的所有离线消息
     *
     * @param uname
     * @return
     */
    @Override
    public List<SocketMessageEntity> offlineRecord(String uname) {
        if (StrUtil.isEmpty(uname)) {
            return null;
        }
        QueryWrapper<ChatRecord> wrapper = ChatRecord.wrapper();
        wrapper.select("id", "content").eq("to_name", uname)
                .eq("msg_type", 2).orderByAsc("sort_num");
        List<ChatRecord> records = list(wrapper);
        if (CollUtil.isEmpty(records)) {
            // 没有离线消息直接返回
            return null;
        }

        // 将需要删除的离线消息ID记录
        List<Long> deleteIds = CollUtil.list(false);
        // 组件消息体
        List<SocketMessageEntity> messages = CollUtil.list(false);
        for (ChatRecord record : records) {
            String message = record.getContent();
            // 判断是否JSON格式
            if (JSONUtil.isJsonObj(message)) {
                SocketMessageEntity messageEntity = JSONUtil.toBean(message, SocketMessageEntity.class);
                messages.add(messageEntity);
            }
            deleteIds.add(record.getId());
        }
        // 删除已经发送的离线消息
        removeByIds(deleteIds);
        return messages;
    }
}
